home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / 82586.ASM < prev    next >
Assembly Source File  |  1992-01-07  |  26KB  |  997 lines

  1. i82586_version    equ    2
  2.   ifndef DAN
  3. DAN    equ    4            ; 4 seems to work best.
  4.   endif
  5.  
  6. ;
  7. ; Code that is common between 82586 implementations.
  8. ;
  9.  
  10. ; Ported from Tim Krauskopf's micnet.asm, an assembly language
  11. ; driver for the MICOM-Interlan NI5210, by Russell Nelson.  Any bugs
  12. ; are due to Russell Nelson.
  13. ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  14. ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
  15.  
  16. ; Copyright, 1988-1992, Russell Nelson, Crynwr Software
  17.  
  18. ;   This program is free software; you can redistribute it and/or modify
  19. ;   it under the terms of the GNU General Public License as published by
  20. ;   the Free Software Foundation, version 1.
  21. ;
  22. ;   This program is distributed in the hope that it will be useful,
  23. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25. ;   GNU General Public License for more details.
  26. ;
  27. ;   You should have received a copy of the GNU General Public License
  28. ;   along with this program; if not, write to the Free Software
  29. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  
  31. ;
  32. ;  Structure elements specific to the Intel 82586 chip
  33. ;
  34.  
  35. ; System Configuration Pointer
  36. scp_struc    struc
  37. scp_bus        db    ?,?,?, ?,?,?    ; bus use flag (0=16 bit, 1=8 bit).
  38. scp_ptr        dd    ?        ; 24pointer to iscp
  39. scp_struc    ends
  40.  
  41. ; Intermediate System Configuration Pointer
  42. iscp_struc    struc
  43. iscp_busy    db    ?,?        ; busy flag (zeroed after init).
  44. iscp_offset    dw    ?        ; 16pointer to iscp
  45. iscp_base    dd    ?        ; base for all 16 pointers, lo, hi
  46. iscp_struc    ends
  47.  
  48. ; System Control Block
  49. scb_struc    struc
  50. scb_stat    dw    ?        ; status
  51. scb_com        dw    ?        ; command
  52. scb_cbl        dw    ?        ; 16pointer to command block list
  53. scb_rfa        dw    ?        ; 16pointer to receive frame list
  54. scb_serrs    dw    4 dup(?)    ; 4 words of error counts
  55. scb_struc    ends
  56.  
  57. ; (Received) Frame Descriptor
  58. fd_struc    struc
  59. fd_status    dw    ?        ; status word for frame
  60. fd_eol        dw    ?        ; end of FD list flag
  61. fd_link        dw    ?        ; 16pointer to next FD
  62. fd_ptr        dw    ?        ; 16pointer to list of RBD's
  63. fd_dest        db    EADDR_LEN dup(?); 48 bits of destination
  64. fd_source    db    EADDR_LEN dup(?); 48 bits of source
  65. fd_cnt        dw    ?        ; length field of frame.
  66. fd_struc    ends
  67.  
  68. ; Receive Buffer Descriptor
  69. rbd_struc    struc
  70. rbd_status    dw    ?        ; status word in RBD
  71. rbd_link    dw    ?        ; 16pointer to next RBD
  72. rbd_ptr        dd    ?        ; 24pointer to actual buffer
  73. rbd_size    dw    ?        ; size of the buffer
  74. rbd_struc    ends
  75.  
  76. ; Transmit Command Block
  77. tcb_struc    struc
  78. tcb_status    dw    ?        ; status word for xmit
  79. tcb_com        dw    ?        ; command to transmit
  80. tcb_link    dw    ?        ; 16pointer to next command
  81. tcb_ptr        dw    ?        ; 16pointer to xmit TBD
  82. tcb_addr    db    EADDR_LEN dup(?); destination address
  83. tcb_len        dw    ?
  84. tcb_struc    ends
  85.  
  86. ; Transmit Buffer Descriptor
  87. tbd_struc    struc
  88. tbd_status    dw    ?        ; bit 15=EOF, 13-0=actual count
  89. tbd_link    dw    ?        ; 16pointer to next TBD
  90. tbd_ptr        dd    ?        ; 24pointer to buffer
  91. tbd_struc    ends
  92.  
  93. ; all commands have at least the following:
  94. cmd_struc    struc
  95. cmd_status    dw    ?        ; status word
  96. cmd_com        dw    ?        ; command word.
  97. cmd_struc    ends
  98.  
  99. ; MC-SETUP Command Block
  100. mcb_struc    struc
  101. mcb_status    dw    ?        ; status word for multicast
  102. mcb_com        dw    ?        ; command to setup multicast
  103. mcb_link    dw    ?        ; 16pointer to next command
  104. mcb_cnt        dw    ?        ; number of multicast addresses.
  105. mcb_struc    ends
  106.  
  107. ; TDR Command Block
  108. tdr_struc    struc
  109. tdr_status    dw    ?        ; status word for TDR
  110. tdr_com        dw    ?        ; command to setup TDR
  111. tdr_link    dw    ?        ; 16pointer to next command
  112. tdr_time    dw    ?        ; error bits and time
  113. tdr_struc    ends
  114.  
  115. ;Memory allocation.
  116.  
  117. SCPTR    EQU    0fff6h            ; hardwired address for SCP
  118. ISCPTR    EQU    0ffeeh            ; my address for ISCP, points to SCB
  119. SCB    EQU    ISCPTR - 16        ; system control block base
  120. CCBPTR    EQU    SCB - 18        ; offset of configure command block
  121. TBDPTR    EQU    CCBPTR - 8        ; xmit BD offset
  122. TCBPTR    EQU    TBDPTR - 16        ; xmit CB offset
  123. TBUFPTR    EQU    TCBPTR - GIANT        ; xmit buffer offset
  124. ;the receive buffers appear at lower addresses than TBUFPTR.
  125. RBUFLEN    EQU    200
  126. RBUF_TOTAL    equ    (size fd_struc) + (size rbd_struc) + RBUFLEN
  127. FDBASE        equ    TBUFPTR - RBUF_TOTAL
  128.  
  129. memory_begin    dw    ?
  130.  
  131.     public    rcv_modes
  132. rcv_modes    dw    7        ;number of receive modes in our table.
  133.         dw    0               ;There is no mode zero
  134.         dw    0
  135.         dw    rcv_mode_2
  136.         dw    rcv_mode_3
  137.         dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  138.         dw    0
  139.         dw    rcv_mode_6
  140.  
  141. firstfd        dw    FDBASE        ; start of FD queue
  142. lastfd        dw    0        ; end of the FD chain
  143. lastbd        dw    0        ; end of the BD chain
  144. flag        dw    0
  145.  
  146.  
  147. ;
  148. ; Configuration block for 82586, this comprises one config command
  149. ;  Parameters taken from MICOM driver
  150. ;
  151. CBCONF    DW    0        ; status word
  152.     DW    8002H        ; end of command list + configure command
  153.     DW    0ffffh        ; link to next command (not used)
  154.     DW    080CH        ; fifo=8, byte count=C
  155.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  156.     DW    6000H        ; IFS = 60h
  157.     DW    0F200H        ; retry=F, slot time=200h
  158. CBCONF_FLAGS    label    byte
  159.     DW    0        ; flags, set to 1 for promiscuous
  160. CBCONF_MINLEN    label    byte
  161.     DW    40H        ; min frame length=40h
  162.  
  163.  
  164. doca_wait:
  165. ;enter with ax = command to execute, es = base_addr.
  166. ;exit with nc if the command ran to completion.
  167. ;exit with cy if the command timed out.  Eventually we'll also reset the chip.
  168.     mov    es:[SCB].scb_com,ax    ;set the command.
  169.  
  170.     mov    si,es:[SCB].scb_cbl    ;
  171.     mov    es:[si].cmd_status,0    ; status word of specific command
  172.     and    ax,0700h
  173.     cmp    ax,0100h        ; is it an action command?
  174.     jne    doca_wait_a        ; no, any other
  175.  
  176.     call    doca
  177.  
  178. comment \
  179. Quoting from the D-Step Errata Revision 2.0:
  180.  
  181. The value for the deadman timer should be greater than the longest
  182. command execution time.  The command which can take the longest time
  183. to execute is the transmit command, assuming maximum retries.  To
  184. determine the maximum amount of time the transmit command may take,
  185. one must use the following equation: 7143 ST + 14 f, where ST stands
  186. for Slot Time and f = Maximum Frame Size + IFS + Preamble.  For
  187. Ethernet/IEEE 802.3 where ST = 512 bits, f = 12144 bits, Preamble =
  188. 64 bits, IFS  96 bits, and one bit = 0.1 usec, the deadman timeout
  189. should be greater than 0.369 seconds.
  190.  
  191. \
  192.  
  193.     mov    ax,14            ;36.4 ticks / seconds * .369 seconds
  194.     call    set_timeout
  195. doca_wait_1:
  196.     test    es:[si].cmd_status,8000h    ; is command complete?
  197.     jnz    doca_wait_2        ;yes.
  198.     call    do_timeout        ;did we time out yet?
  199.     jne    doca_wait_1        ;not yet.
  200. ;reset the chip here, then Configure, IA-Setup, and MC-Setup.
  201.     stc                ;timeout -- uh-oh.
  202.     ret
  203. doca_wait_2:
  204.     clc
  205.     ret
  206.  
  207. doca_wait_a:
  208.     call    doca
  209. doca_wait_a_0:
  210.     cmp    es:[SCB].scb_com,0    ; has the command been accepted?
  211.     jnz    doca_wait_a_0        ; not yet.
  212.     clc
  213.     ret
  214.  
  215.  
  216.     include    timeout.asm
  217.     include    movemem.asm
  218.  
  219.     public    as_send_pkt
  220. ; The Asynchronous Transmit Packet routine.
  221. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  222. ;   interrupts possibly enabled.
  223. ; Exit with nc if ok, or else cy if error, dh set to error number.
  224. ;   es:di and interrupt enable flag preserved on exit.
  225. as_send_pkt:
  226.     ret
  227.  
  228.     public    drop_pkt
  229. ; Drop a packet from the queue.
  230. ; Enter with es:di -> iocb.
  231. drop_pkt:
  232.     assume    ds:nothing
  233.     ret
  234.  
  235.     public    xmit
  236. ; Process a transmit interrupt with the least possible latency to achieve
  237. ;   back-to-back packet transmissions.
  238. ; May only use ax and dx.
  239. xmit:
  240.     assume    ds:nothing
  241.     ret
  242.  
  243.  
  244.     public    send_pkt
  245. send_pkt:
  246. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  247. ;  (only if the high-performance bit is set in driver_function)
  248. ;enter with ds:si -> packet, cx = packet length.
  249. ;exit with nc if ok, or else cy if error, dh set to error number.
  250.     assume    ds:nothing
  251.     mov    es,base_addr        ; base for board
  252.  
  253.     cmp    cx,GIANT        ; Is this packet too large?
  254.     ja    send_pkt_toobig
  255.  
  256.     mov    dx,cx            ; save a copy, might be less than 60, ok
  257.  
  258.     cmp    dx,RUNT            ; minimum length for Ether
  259.     jnb    oklen
  260.     mov    dx,RUNT            ; make sure size at least RUNT
  261. oklen:
  262.     mov    di,TBUFPTR        ; start of xmit buffer
  263.  
  264. ;
  265. ;  check for previous xmit
  266. ;
  267. xwait:
  268.     mov    bx,es:[SCB].scb_com    ; has previous command been accepted?
  269.     or    bx,bx
  270.     jnz    xwait            ; not there yet, wait for it
  271. wait_for_transmit_to_complete:
  272.     test    word ptr es:[TCBPTR],4000h
  273.     jnz    wait_for_transmit_to_complete
  274. ;
  275. ;  move the data using word moves.
  276. ;
  277.     call    movemem
  278. ;
  279. ;  put the correct size into the TBD
  280. ;
  281.     or    dx,08000h            ; end of frame bit flag
  282.     mov    es:[TBDPTR].tbd_status,dx    ; store it
  283.     mov    es:[TCBPTR].tcb_status,0    ; zero status wd
  284.     mov    es:[TCBPTR].tcb_com,8004h    ; xmit command in TCB
  285.     mov    es:[SCB].scb_com,0100h        ; execute command
  286.     mov    es:[SCB].scb_cbl,TCBPTR    ; say where xmit command is
  287.  
  288.     call    doca
  289.  
  290.     clc
  291.     ret
  292. send_pkt_toobig:
  293.     mov    dh,NO_SPACE
  294.     stc
  295.     ret
  296.  
  297.  
  298. rcv_mode_2:
  299.     and    CBCONF_FLAGS,not 3
  300.     or    CBCONF_FLAGS,2        ;disable broadcasts.
  301.     mov    CBCONF_MINLEN,40h
  302.     jmp    short reconfigure
  303. rcv_mode_4:
  304. rcv_mode_3:
  305.     and    CBCONF_FLAGS,not 3    ;clear promiscuous mode.
  306.     mov    CBCONF_MINLEN,40h
  307.     jmp    short reconfigure
  308. rcv_mode_6:
  309.     and    CBCONF_FLAGS,not 3
  310.     or    CBCONF_FLAGS,1        ;set promiscuous mode.
  311.     mov    CBCONF_MINLEN,0        ;allow runts.
  312. reconfigure:
  313.     mov    es,base_addr        ;get the base address for the board.
  314.     mov    si,offset CBCONF    ; configure command
  315.     mov    di,CCBPTR        ; where command will reside
  316.     mov    cx,9
  317.     rep    movsw            ; copy to board
  318. ;
  319. ;  issue the configure command
  320. ;
  321.     mov    es:[SCB].scb_cbl,CCBPTR    ; where conf command is
  322.     mov    es:[SCB].scb_serrs[0],0    ; zero errs field
  323.     mov    es:[SCB].scb_serrs[2],0    ; zero errs field
  324.     mov    es:[SCB].scb_serrs[4],0    ; zero errs field
  325.     mov    es:[SCB].scb_serrs[6],0    ; zero errs field
  326.     mov    ax,100h            ; do-command command
  327.     call    doca_wait
  328.     ret
  329.  
  330.  
  331.     public    set_multicast_list
  332. set_multicast_list:
  333. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  334. ;return nc if we set all of them, or cy,dh=error if we didn't.
  335.     assume    ds:code
  336.     mov    es,base_addr
  337.     mov    es:[SCB].scb_cbl,TBUFPTR    ;use the transmit buffer.
  338.  
  339.     mov    es:[TBUFPTR].mcb_status,0    ;status word
  340.     mov    es:[TBUFPTR].mcb_com,08003h    ;command word for mc-setup + EL
  341.     mov    es:[TBUFPTR].mcb_link,-1    ;no command link.
  342.     mov    di,TBUFPTR + mcb_cnt
  343.     mov    ax,cx            ;store the count.
  344.     stosw
  345.     rep    movsb
  346.  
  347. comment \ avoid deferred execution of a CU command during reception.
  348. If a command is executed with a length of 18 to 20 bytes, and a frame
  349. is received, the 82586 may deadlock with HOLD active.  We avoid this
  350. problem by suspending the receiver. \
  351.  
  352.     mov    ax,30h            ;suspend frame receiving.
  353.     call    doca_wait
  354.  
  355.     mov    ax,100h            ; do-command command
  356.     call    doca_wait
  357.     jnc    set_multicast_2
  358.  
  359.     mov    ax,20h            ;resume frame receiving.
  360.     call    doca_wait
  361.  
  362.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  363.     stc
  364.     ret
  365. set_multicast_2:
  366.     mov    ax,20h            ;resume frame receiving.
  367.     call    doca_wait
  368.  
  369.     clc
  370.     ret
  371.  
  372.  
  373.     public    terminate
  374. terminate:
  375.     assume    ds:code
  376.     ret
  377.  
  378.     public    reset_interface
  379. reset_interface:
  380. ;reset the interface.
  381. ;we don't do anything.
  382.     assume    ds:nothing
  383.     ret
  384.  
  385.  
  386. ;called when we want to determine what to do with a received packet.
  387. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  388.     extrn    recv_find: near
  389.  
  390. ;called after we have copied the packet into the buffer.
  391. ;enter with ds:si ->the packet, cx = length of the packet.
  392.     extrn    recv_copy: near
  393.  
  394.     extrn    count_in_err: near
  395.     extrn    count_out_err: near
  396.  
  397.     public    recv
  398. recv:
  399.   ifdef IO_INTCLR
  400.     loadport            ;clear the interupt latch.
  401.     setport    IO_INTCLR
  402.     out    dx,al
  403.   endif
  404.  
  405.     mov    flag, 1
  406. ;called from the recv isr.  All registers have been saved, and ds=cs.
  407. ;Upon exit, the interrupt will be acknowledged.
  408. recv1:
  409.     mov    ds,base_addr    ; base for board
  410.     assume    ds:nothing
  411.  
  412.     mov    ax,ds:[SCB].scb_stat    ;get the status.
  413. recv_isr_1:
  414.     cmp    ds:[SCB].scb_com,0    ;has previous command been accepted?
  415.     jne    recv_isr_1        ;no -- keep waiting.
  416.  
  417.     and    ax,0f000h        ;isolate the ACK bits to make a
  418.                     ;  command to ack the interrupt.
  419.   if DAN and 1
  420.     jz    recv_isr_2
  421.   endif
  422.  
  423.     mov    ds:[SCB].scb_com,ax    ;set the command.
  424.     call    doca
  425. recv_isr_2:
  426.     cmp    ds:[SCB].scb_com,0    ; has the command been accepted?
  427.     jnz    recv_isr_2        ; not yet.
  428.  
  429. ;  Get whatever packets are on the board
  430. ;
  431.     mov    bx,firstfd    ; get addr of first FD in list
  432.     mov    ax,[bx].fd_status    ; status word of frame
  433.     test    ax,08000h    ; frame written?
  434.     jnz    okframe
  435.  
  436.     jmp    ru_start    ; no, restore receiver if necessary
  437. frame_bad:
  438.     call    count_in_err
  439. ptrupdate_j_1:
  440.     jmp    ptrupdate
  441.  
  442. ;  we have a frame, read it in
  443. ;
  444. okframe:
  445.     test    ax,02000h        ;check frame OK bit
  446.     jz    frame_bad        ;bad, fix it.
  447.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  448.     xor    cx,cx            ;start with zero bytes.
  449. countbuf:                ;es:di is already set to receive packet
  450.     mov    dx,si            ;save a copy of current BD ptr
  451.     mov    ax,[si].rbd_status    ;get status and count word for BD
  452.     test    ax,04000h        ;is count field there?
  453.     jz    ptrupdate_j_1        ;no - we give up here.
  454.     add    cl,al            ;add the count into cx.
  455.     adc    ch,0
  456.     mov    si,[si].rbd_link    ;go to next BD in list
  457.     test    ax,8000h        ;is this the last frame?
  458.     je    countbuf        ;no - keep counting.
  459.  
  460.     push    bx
  461.     push    cx
  462.  
  463.     mov    ax,cs            ;we need ds = code.
  464.     mov    ds,ax
  465.     assume    ds:code
  466.  
  467.     mov    es,base_addr        ;get a pointer to their type.
  468.     mov    di,es:[bx].fd_ptr    ;get pointer to buffer descriptor
  469.     mov    di,es:[di].rbd_ptr.offs    ;get offset of data
  470.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  471.                     ;  point to the packet type.
  472.  
  473.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  474.     mov    ax, es:[di]
  475.     xchg    ah, al
  476.     cmp     ax, 1500
  477.     ja    BlueBookPacket
  478.     inc    di            ;set di to 802.2 header
  479.     inc    di
  480.     mov    dl, IEEE8023
  481. BlueBookPacket:
  482.     call    recv_find        ;look up our type.
  483.  
  484.     pop    cx
  485.     pop    bx
  486.     mov    ds,base_addr        ;restore ds to the board.
  487.     assume    ds:nothing
  488.  
  489.     mov    ax,es            ;is this pointer null?
  490.     or    ax,di
  491.     je    ptrupdate        ;yes - just free the frame.
  492.  
  493.     push    cx
  494.     push    es            ;remember where the buffer pointer is.
  495.     push    di
  496.   if DAN and 2
  497.     push    cx
  498.   endif
  499.  
  500.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  501. copybuf:
  502.     mov    dx,si            ;save a copy of current BD ptr
  503.     xor    ch,ch            ;200 bytes is largest this can be
  504.     mov    cl,byte ptr [si].rbd_status;get count word for BD
  505.     mov    si,[si].rbd_ptr.offs    ;get offset of data
  506.   if DAN and 2
  507.     pop    ax
  508.     sub    ax, cx
  509.     jc    copydone
  510.     push    ax
  511.   ENDIf
  512.     call    movemem
  513.     mov    si,dx            ;get back current BD ptr
  514.     test    [si].rbd_status,8000h    ;check EOF bit
  515.     mov    si,[si].rbd_link    ;go to next BD in list
  516.     jz    copybuf            ;not done, keep copying it.
  517.  
  518.   if DAN and 2
  519.     pop    cx
  520. copydone:
  521.   endif
  522.     pop    si            ;now give the frame to the client.
  523.     pop    ds
  524.     pop    cx
  525.     assume    ds:nothing
  526.  
  527.     call    recv_copy
  528. ;
  529. ;  we are done with the frame, do the list management
  530. ;
  531. ptrupdate:
  532.     push    cs
  533.     pop    ds
  534.     assume    ds:code
  535.     mov    es,base_addr        ; reload board segment
  536.  
  537.     mov    si,es:[bx].fd_ptr    ; first BD in frame list
  538. nextbd:
  539.     mov    cx,es:[si].rbd_status    ; count word for BD, EOF bit
  540.     test    cx,08000h        ; EOF bit, if set, save si in lastbd
  541.     jnz    dolastbd
  542.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  543.     cmp    si,lastbd        ; see if we are wrapping
  544.     jz    dolastbd        ; yes, just undo it
  545.     mov    si,es:[si].rbd_link    ; follow link
  546.     jmp    nextbd
  547. dolastbd:
  548.     mov    di,lastbd        ; where end of BD list is now
  549.     mov    lastbd,si        ; store last known BD
  550.     mov    es:[si].rbd_size,08000h+200; end of list here
  551.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  552. ; size field for not end of list
  553.     mov    es:[di].rbd_size,200    ; remove old end-of-list
  554.  
  555. ;
  556. ;  update the FD list flags, new end-of-list
  557. ;
  558.     mov    es:[bx].fd_eol,08000h    ; store new EOL
  559.     mov    es:[bx].fd_status,0    ; clear status word for frame
  560.     mov    di,lastfd        ; get old end-of-list
  561.     mov    es:[di].fd_eol,0    ; zero old one
  562.     mov    lastfd,bx        ; update stored pointer
  563.     mov    si,es:[bx].fd_link    ; where next fd is
  564.     mov    firstfd,si        ; store that info for next time
  565.   if DAN and 4
  566.     jmp    recv1
  567.   endif
  568.  
  569. ru_start:
  570. ; re-start receive unit
  571. ;
  572. ;  check to see if the receiver went off because of no resources
  573. ;  and restart receiver if necessary
  574. ;
  575.     push    cs
  576.     pop    ds
  577.     mov    es,base_addr
  578.     mov    ax,es:[SCB].scb_stat    ; status word for SCB
  579.     and    ax,070h        ; receiver status
  580.     cmp    al,020h        ; receiver has no resources
  581.     jnz    hasres
  582.   if DAN and 8
  583.     cmp    flag, 1
  584.     jnz    ru_start1
  585.     mov    flag, 0
  586.     jmp    recv1
  587.   endif
  588.  
  589. ru_start1:
  590.     call    count_out_err
  591. ;
  592. ;  setup lists for starting the RU on the chip
  593. ;  we know that there isn't anything in the buffer that we want
  594. ;
  595.  
  596.     mov    bx,firstfd        ; get first FD on free list (assume free)
  597.     mov    es:[SCB].scb_rfa,bx    ; put into SCB
  598.     mov    si,lastbd        ; pointer to a BD, end of chain
  599.     mov    ax,es:[si].rbd_link    ; pointer to next BD
  600.     mov    es:[bx].fd_ptr,ax    ; set to start of BDs
  601. ;
  602. ;
  603. ;  Start the RU, doesn't need CB, only SCB parms.
  604. ;   command, to start receiving again
  605. ;
  606.     mov    ax,10h            ; start RU
  607.     call    doca_wait
  608. hasres:
  609. ;I don't we need to wait here because we haven't done anything to wait for.
  610.     ret
  611.  
  612.  
  613.     public    recv_exiting
  614. recv_exiting:
  615. ;called from the recv isr after interrupts have been acknowledged.
  616. ;Only ds and ax have been saved.
  617.     assume    ds:nothing
  618.     ret
  619.  
  620.  
  621.     public    set_address
  622. set_address:
  623.     assume    ds:nothing
  624. ;enter with ds:si -> Ethernet address, CX = length of address.
  625. ;exit with nc if okay, or cy, dh=error if any errors.
  626.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  627.     je    set_address_4
  628.     mov    dh,BAD_ADDRESS
  629.     stc
  630.     jmp    short set_address_done
  631. set_address_4:
  632.  
  633. ;  Next step, load our address into the board
  634. ;     reuses the space that the configure command used, with different command
  635. ;
  636.     mov    es,base_addr        ; set to base address
  637.     mov    es:[SCB].scb_cbl,CCBPTR    ; say where conf command is
  638.  
  639.     mov    di,CCBPTR        ; start of config command block
  640.     xor    ax,ax
  641.     stosw                ; zero status word for commmand
  642.     mov    ax,8001h        ; IA setup command + EL
  643.     stosw
  644.     xor    ax,ax
  645.     dec    ax
  646.     stosw                ; set link value to -1 (unused)
  647.  
  648.     rep    movsb            ; move their ethernet address in.
  649. ;
  650. ;  start the IA setup command
  651. ;
  652.     mov    ax,100h            ; do-command command
  653.     call    doca_wait
  654.     jnc    set_address_okay
  655.     mov    dh,-1            ; no error in the list applies.
  656.     jmp    short set_address_done
  657. set_address_okay:
  658.     mov    cx,EADDR_LEN        ;return their address length.
  659.     clc
  660. set_address_done:
  661.     push    cs
  662.     pop    ds
  663.     assume    ds:code
  664.     ret
  665.  
  666.  
  667. end_resident    label    byte
  668.  
  669. timeout_msg    db    "Timed out while initializing the board.",CR,LF,'$'
  670. our_address    db    6 dup(?)    ;temporarily hold our address
  671.  
  672. addr_bad_msg    db    "Invalid memory address.",CR,LF,'$'
  673.  
  674.   if 0
  675. tdr_warn_msg    db    "TDR: ",'$'
  676. tdr_ok_msg    db    "Ok",CR,LF,'$'
  677. tdr_none_msg    db    "Ethernet card doesn't seem to be plugged in.",CR,LF,'$'
  678. tdr_open_msg    db    " clocks away is an OPEN (not completely reliable)",CR,LF,'$'
  679. tdr_short_msg    db    " clocks away is a SHORT (not completely reliable)",CR,LF,'$'
  680.   endif
  681.  
  682. mem8_16        db    2        ; 1 for 16k, 2 for 8k
  683.  
  684.     extrn    set_recv_isr: near
  685.     extrn    maskint: near
  686.  
  687. ;enter with si -> argument string, di -> word to store.
  688. ;if there is no number, don't change the number.
  689.     extrn    get_number: near
  690.  
  691. ;enter with dx -> name of word, di -> dword to print.
  692.     extrn    print_number: near
  693.  
  694. ;enter with ax = number to print.
  695.     extrn    decout: near
  696.  
  697. timeout_error:
  698.     mov    dx,offset timeout_msg
  699.     jmp    short error
  700. error:
  701.     mov    ah,9
  702.     int    21h
  703.     stc
  704.     ret
  705.  
  706. ;
  707. ;  data for configuring and setting up the board
  708. ;
  709. ;  chip always looks at SCP for config info which points to ISCP for the
  710. ;  pointer to the CONTROL BLOCK which handles everything from there.
  711. ;  Kind of indirect, but it works.
  712. ;
  713. SCP    DB    0            ; bus use flag (0=16 bit, 1=8 bit).
  714.  
  715.     public    etopen
  716. etopen:
  717.     mov    al,int_no
  718.     call    maskint            ;disable these interrupts.
  719.  
  720.     cmp    base_addr.offs,0    ;low word of segment can't be zero.
  721.     je    etopen_1
  722.     cmp    base_addr.segm,0    ;high word of segment must be zero.
  723.     je    etopen_2
  724. etopen_1:
  725.     mov    dx,offset addr_bad_msg
  726.     mov    ah,9
  727.     int    21h
  728.  
  729.     stc
  730.     ret
  731. etopen_2:
  732.  
  733. ;  Initialize the Ethernet board, set receive type.
  734. ;
  735. ;  check for correct EPROM location
  736. ;
  737.     call    check_board
  738.  
  739. ;
  740. ;  Turn off interrupts, I don't want them
  741. ;
  742.   ifdef IOINTOF
  743.     loadport
  744.     setport IOINTOF
  745.     out    dx,al
  746.   endif
  747. ;
  748. ;  Disconnect from network
  749. ;
  750.   ifdef IODIS
  751.     loadport
  752.     setport    IODIS
  753.     out    dx,al
  754.   endif
  755.  
  756. ;
  757. ;  Initialize the Ethernet board.
  758. ;
  759.     sub    base_addr,0e00h
  760.     mov    di,0e000h        ;our initial base address.
  761.     mov    si,ISCPTR-2        ;try the init down a little.
  762.  
  763. ;
  764. ;  Now discern the end of memory by repeatedly re-initializing the board
  765. ;  until the BUSY flag in the ISCP gets reset.
  766. ;
  767. re_discern:
  768.     mov    es,base_addr        ;remember where we think it starts.
  769.     call    init_root        ;did we find our memory size?
  770.     jc    confng            ;no, keep trying.
  771.     inc    si            ;yes, see if we found the real one.
  772.     inc    si
  773.     call    init_root        ;try initializing it in a different locn.
  774.     jnc    confok            ;it worked!  we've found the root.
  775.     dec    si            ;it didn't work, keep trying.
  776.     dec    si
  777. confng:
  778.     or    di,di            ;did we try all 64K?
  779.     je    confbad            ;yes.
  780.  
  781.     add    base_addr,200h        ;advance the segment by 2000h bytes.
  782.     sub    di,2000h        ;retreat the offset by 2000h bytes.
  783.     jmp    re_discern        ;try this next higher address.
  784. confbad:
  785.     sti
  786.     jmp    timeout_error
  787.  
  788. confok:
  789.     mov    memory_begin,di
  790.     call    reconfigure
  791.     jc    confbad
  792.  
  793. ;
  794. ;  Ask the board for the Ethernet address, and then use set_address to set it.
  795. ;
  796.     push    ds
  797.     pop    es
  798.     mov    di,offset our_address
  799.     mov    cx,EADDR_LEN
  800.     call    get_address
  801.  
  802.     mov    si,offset our_address
  803.     mov    cx,EADDR_LEN
  804.     call    set_address
  805.     jnc    store_address_2
  806.     sti
  807.     jmp    timeout_error
  808. store_address_2:
  809. ;
  810. ;  IA sent, setup all of the other data structures on the board
  811. ;  start with xmit command descriptors
  812. ;
  813.     mov    di,TCBPTR
  814.     mov    es:[di].tcb_status,0
  815.     mov    es:[di].tcb_com,08004h
  816.     mov    es:[di].tcb_link,-1
  817.     mov    es:[di].tcb_ptr,TBDPTR
  818.  
  819.     add    di,(size tcb_struc)
  820.  
  821.     mov    es:[di].tbd_status,0
  822.     mov    es:[di].tbd_link,0
  823.     mov    es:[di].tbd_ptr.offs,TBUFPTR
  824.     mov    es:[di].tbd_ptr.segm,0
  825.  
  826. ; Note that we allocate fd's, rbd's, and buffers all at the same time.  This
  827. ; doesn't mean that each pair of fd's and rbd's necessarily have anything to
  828. ; do with each other.  We just allocate them together because we want to have
  829. ; the same number of each, and it's easier to compute that way.
  830.  
  831.     mov    di,TBUFPTR        ;get the last buffer.
  832.  
  833.     mov    ax,di            ;compute the amount of free memory.
  834.     sub    ax,memory_begin
  835.     xor    dx,dx
  836.     mov    bx,RBUF_TOTAL        ;each buffer takes this much.
  837.     div    bx
  838.     mov    cx,ax            ;put the number of buffers into cx.
  839.  
  840. init_rbuff_0:
  841.     sub    di,RBUF_TOTAL        ;back the pointer down by a little.
  842.  
  843. ;init the FD.
  844.     mov    es:[di].fd_status,0
  845.     mov    es:[di].fd_eol,0
  846.     mov    es:[di].fd_ptr,-1
  847.     lea    ax,[di]-RBUF_TOTAL    ;get the address of the next buffer.
  848.     mov    es:[di].fd_link,ax
  849.  
  850. ;init the BD.
  851.     lea    bx,[di + (size fd_struc)]
  852.     mov    es:[bx].rbd_status,0
  853.     lea    ax,[bx-RBUF_TOTAL]    ;make a pointer to the next BD
  854.     mov    es:[bx].rbd_link,ax
  855.     lea    ax,[bx+(size rbd_struc)]    ;make a pointer to the buffer.
  856.     mov    es:[bx].rbd_ptr.offs,ax
  857.     mov    es:[bx].rbd_ptr.segm,0
  858.     mov    es:[bx].rbd_size,RBUFLEN    ;length of the buffer.
  859.  
  860.     loop    init_rbuff_0
  861.  
  862. init_rbuff_1:
  863. ;patch the parameters of the last FD and BD so they link around to the head.
  864.     mov    es:[di].fd_eol,8000h
  865.     mov    es:[di].fd_link,FDBASE
  866.     mov    lastfd,di
  867.  
  868.     lea    bx,[di + (size fd_struc)]
  869.     mov    es:[bx].rbd_link,FDBASE + (size fd_struc)
  870.     mov    es:[bx].rbd_size,RBUFLEN + 8000h
  871.     mov    lastbd,bx
  872.  
  873. ;now put the location of the first rbd into the first fd.
  874.     mov    es:[FDBASE].fd_ptr,FDBASE  + (size fd_struc)
  875.  
  876.     call    enable_network
  877.  
  878.   if 0    ;this message only confuses users.
  879.  
  880.     mov    dx,offset tdr_warn_msg    ;warn them that the 82586 TDR sucks.
  881.     mov    ah,9
  882.     int    21h
  883.  
  884. ;
  885. ; Test to see if the network is okay.
  886. ;
  887.     mov    di,CCBPTR        ; start of config command block
  888.     xor    ax,ax            ; zero status word for commmand
  889.     stosw
  890.     mov    ax,8005h        ; TDR command + EL
  891.     stosw
  892.     xor    ax,ax
  893.     dec    ax
  894.     stosw                ; set link value to -1 (unused)
  895.     inc    ax
  896.     stosw                ; zero time result.
  897.  
  898.     mov    ax,100h            ; do-command command
  899.     call    doca_wait
  900.     jnc    do_tdr_2        ; finished okay.
  901.     mov    ax,2000h        ; treat a timeout as an open
  902.     jmp    short do_tdr_5
  903. do_tdr_2:
  904.     mov    ax,word ptr es:[CCBPTR].tdr_time
  905. do_tdr_5:
  906.     mov    dx,offset tdr_ok_msg
  907.     test    ax,8000h
  908.     jne    do_tdr_3
  909.     mov    dx,offset tdr_short_msg
  910.     test    ax,2000h
  911.     je    do_tdr_4
  912.     mov    dx,offset tdr_none_msg
  913.     cmp    ax,2000h
  914.     je    do_tdr_3
  915.     mov    dx,offset tdr_open_msg
  916. do_tdr_4:
  917.     push    dx
  918.     and    ax,2048-1
  919.     xor    dx,dx
  920.     call    decout
  921.     pop    dx
  922. do_tdr_3:
  923.     mov    ah,9
  924.     int    21h
  925.   endif
  926.  
  927. ;
  928. ;  Start the RU, doesn't need CB, only SCB parms.
  929. ;   command, to start receiving
  930. ;
  931.     mov    es:[SCB].scb_rfa,FDBASE    ; set to frame descriptors
  932.     mov    ax,10h            ; start RU
  933.     call    doca_wait
  934. ;
  935. ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
  936. ;
  937.     mov    ax,es:[SCB].scb_stat    ;get the status.
  938.     and    ax,0f000h        ;isolate the ACK bits.
  939.     mov    es:[SCB].scb_com,ax    ;make a command to
  940.                     ;acknowledge the interrupt.
  941.     call    doca
  942. ;
  943. ; Now hook in our interrupt
  944. ;
  945.     call    set_recv_isr
  946.  
  947.     sti
  948.  
  949.     mov    al, int_no        ; Get board's interrupt vector
  950.     add    al, 8
  951.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  952.     jb    set_int_num        ; No.
  953.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  954. set_int_num:
  955.     xor    ah, ah            ; Clear high byte
  956.     mov    int_num, ax        ; Set parameter_list int num.
  957.  
  958.     mov    dx,offset end_resident
  959.     clc
  960.     ret
  961.  
  962.  
  963. init_root:
  964. ;enter with es:di -> beginning of our system memory window,
  965. ;  si -> place to put ISC.
  966. ;exit with nc if it worked, cy if it didn't work.
  967.  
  968.     mov    al,SCP
  969.     mov    es:[SCPTR].scp_bus,al
  970.     mov    es:[SCPTR].scp_ptr.offs,si
  971.     mov    es:[SCPTR].scp_ptr.segm,0
  972.  
  973.     mov    es:[si].iscp_busy,1        ;set busy bit.
  974.     mov    es:[si].iscp_offset,SCB        ;point to the SCB.
  975.     mov    es:[si].iscp_base.offs,0    ;scb base.
  976.     mov    es:[si].iscp_base.segm,0    ;scb base.
  977.  
  978.     call    reset_586        ; reset the 586, hardware-specific.
  979.  
  980. ;
  981. ;  Issue a CA to initialize the chip after reset
  982. ;
  983.     call    doca
  984.  
  985.     mov    ax,2            ;don't wait too long.
  986.     call    set_timeout
  987. init_root_2:
  988.     cmp    es:[si].iscp_busy,0    ;did it clear the busy flag?
  989.     je    init_root_1        ;yes.
  990.     call    do_timeout
  991.     jne    init_root_2
  992.     stc
  993.     ret
  994. init_root_1:
  995.     clc
  996.     ret
  997.